var localDataFeatureLayers = [];
var initAddLocalData;
var addDataType;

// var excelGeometries = [];
// var csvGeometries = [];
var shpGeometries = [];
// var jsonGeometries = [];

var excelGraphics = [];
var csvGraphics = [];
var shpGraphics = [];
var jsonGraphics = [];

var localFileName;

var matchGeometries = [];
var matchGraphics = [];
var circleObj = {}; //存储复合检索的缓冲区范围，根据图层名查找
var exceptionGraphicsLayer;

var highlightPolySymbol
var createFeatureLayer;
var fileParse;

var clusterGraphicsObj = {} //存储聚合图的数据，根据图层名查找，用于控制显示区县和街道的数据
var createClusterLayer
var qxGraphicsLayer
require(["esri/map", "esri/layers/FeatureLayer", "esri/layers/GraphicsLayer", "esri/geometry/Point", "esri/geometry/Polyline", "esri/geometry/Polygon",
        "esri/dijit/FeatureTable", "esri/Color", "esri/graphic", "esri/geometry/Circle",
        "esri/symbols/PictureMarkerSymbol",
        "esri/symbols/SimpleMarkerSymbol", "esri/renderers/SimpleRenderer", "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol",
        "esri/renderers/HeatmapRenderer", "esri/layers/LabelClass", "esri/symbols/TextSymbol",
        "esri/InfoTemplate", "esri/tasks/query", "esri/config", "dojo/domReady!"
    ],
    function (Map, FeatureLayer, GraphicsLayer, Point, Polyline, Polygon,
        FeatureTable, Color, Graphic, Circle,
        PictureMarkerSymbol, SimpleMarkerSymbol, SimpleRenderer, SimpleLineSymbol, SimpleFillSymbol, HeatmapRenderer,
        LabelClass, TextSymbol, InfoTemplate, Query, esriConfig) {

        highlightPolySymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([2, 134, 255]), 2), new Color([125, 125, 125, 0.35]));
        const qxSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 193, 7]), 3), new Color([125, 125, 125, 0]));
        const orangeRed = new Color([238, 69, 0, 0.6]);
        const pointSymbol = new SimpleMarkerSymbol("solid", 10, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
            new Color([238, 69, 0]), 0.8), orangeRed);

        //渲染featurelayer的样式
        const pointColor = [238, 69, 0, 144]
        const pointOutlineColor = [238, 69, 0, 180]
        const lineColor = [255, 152, 0];
        const polygonColor = [125, 125, 125, 0.35]
        const polygonOutlineColor = [2, 134, 255]
            console.log(555);
        const localTree = [{
            name: "本地数据",
            LayerList: "lcoalLayerList"
        }, {
            name: "自定义绘制数据",
            LayerList: "drawLayerList"
        }, {
            name: "批量地址检索数据",
            LayerList: "multiAddressLayerList"
        }, {
            name: "复合检索数据",
            LayerList: "multiAroundLayerList"
        }, {
            name: "区域覆盖分析数据",
            LayerList: "areaCoverageLayerList"
        }, {
            name: "轨迹异常分析数据",
            LayerList: "routeExceptionLayerList"
        }, {
            name: "区域特征分析热力图数据",
            LayerList: "heatmapLayerList"
        }, {
            name: "区域特征分析聚合图数据",
            LayerList: "clusterLayerList"
        }, {
            name: "坐标转换数据",
            LayerList: "coordTransferLayerList"
        }];

        initAddLocalData = function () {

            exceptionGraphicsLayer = new GraphicsLayer({
                id: "exceptionGraphicsLayer",
            });
            map.addLayer(exceptionGraphicsLayer);

            //显示区县街道边界的图层
            qxGraphicsLayer = new GraphicsLayer({
                id: "qxGraphicsLayer",
            });
            var render = new SimpleRenderer(qxSymbol);
            qxGraphicsLayer.setRenderer(render)
            map.addLayer(qxGraphicsLayer);

            localTree.forEach(item => {
                var zTreeObj;
                var setting = {
                    check: {
                        enable: true
                    },
                    callback: {
                        onCheck: onLocalTreeCheck,
                        onClick: localzTreeOnClick
                    },
                    view: {
                        showLine: false,
                        addDiyDom: addDiyDom
                    }
                };

                var layerList = item.LayerList;
                var name = item.name;

                var zNodes = [{
                    "name": name,
                    open: true,
                    // children:[{name:"node11"}]
                }];
                zTreeObj = $.fn.zTree.init($("#" + layerList + ""), setting, zNodes);
                var zTree1 = $.fn.zTree.getZTreeObj(layerList);
                console.log('节点->',layerList);
                zTree1.checkAllNodes(false);
                fuzzySearch(layerList, '#localKey', null, true);
            })

        }

        //自定义ztree的导出按钮
        function addDiyDom(treeId, treeNode) {
            if (treeNode.parentTId == null) return;

            var aObj = $("#" + treeNode.tId);
            var editStr = "<span  class='exportIcon' id='diyBtn_" + treeNode.tId + "' title='数据导出' ><i style='font-family: 'Glyphicons Halflings' !important;' class='glyphicon glyphicon-export icon-share'></i></span>";
            aObj.append(editStr);
            var btn = $("#diyBtn_" + treeNode.tId);
            if (btn) btn.bind("click", function () {
                const localDataFeatureLayer = map.getLayer(treeNode.layerId)
                const jsonStr = localDataFeatureLayer._json
                if (jsonStr) {
                    const json = JSON.parse(jsonStr)

                    if (treeNode.parentTId.search("areaCoverageLayerList") != -1) {
                        //区域覆盖的导出需要替换attributes，localDataFeatureLayer._json的attributes为空
                        json.featureSet.features.forEach((item, index) => {
                            item.attributes = {
                                FID: index + 1
                            }
                        })
                    }

                    const featureSetStr = JSON.stringify(json.featureSet)
                    var blob = new Blob([featureSetStr], {
                        type: "text/plain;charset=utf-8"
                    });
                    saveAs(blob, treeNode.name + ".json");
                    console.log(featureSetStr);
                } else {
                    failAlert("导出失败")
                }
            });
        }

        //勾选子节点，控制数据显隐
        function onLocalTreeCheck(e, treeId, treeNode) {
            //批量反向地址数据，勾选后绘制圆
            if (treeId == "multiAroundLayerList") {
                // var layer = map.getLayer(treeNode.layerId);
                var layerId = treeNode.layerId;
                var graphics = circleObj[layerId];

                if (typeof (graphics) != "undefined") {
                    if (treeNode.checked) {
                        graphics.forEach((circle) => {
                            aroundGraphicLayer.add(circle);
                        })
                    } else {
                        aroundGraphicLayer.clear();
                    }
                }
            } else if (treeId == "clusterLayerList" && treeNode.name.endWith("的聚合图")) {
                clusterLayerControl(treeNode);
                return
            }

            const rootName = ["本地数据", "自定义绘制数据", "批量地址检索数据", "复合检索数据", "区域覆盖分析数据", "轨迹异常分析数据", "区域特征分析热力图数据", "区域特征分析聚合图数据", "坐标转换数据"];
            const curName = treeNode.name;

            if (rootName.includes(curName)) {
                //勾选的是根节点，关闭所有子图层
                var zTree = $.fn.zTree.getZTreeObj(treeId);

                var childNodes = zTree.getNodes()[0].children;

                if (treeId == "clusterLayerList") {
                    if (treeNode.checked) {
                        childNodes.forEach(item => {
                            if (item.name.endWith("的聚合图")) {
                                clusterLayerControl(item);
                            } else {
                                map.getLayer(item.layerId).show();
                            }
                        })
                    } else {
                        childNodes.forEach(item => {
                            if (item.name.endWith("的聚合图")) {
                                clusterLayerControl(item);
                            } else {
                                map.getLayer(item.layerId).hide();
                            }
                        })
                    }
                    return
                }

                if (treeNode.checked) {
                    childNodes.forEach(item => {
                        map.getLayer(item.layerId).show();
                    })
                } else {
                    childNodes.forEach(item => {
                        map.getLayer(item.layerId).hide();
                    })
                }

            } else {
                if (treeNode.checked) {
                    map.getLayer(treeNode.layerId).show();
                } else {
                    map.getLayer(treeNode.layerId).hide();
                }
            }

            function clusterLayerControl(treeNode) {
                var layerId = treeNode.layerId;
                var qxLayerID = clusterGraphicsObj[layerId].qxLayerID;
                var jdLayerID = clusterGraphicsObj[layerId].jdLayerID;
                if (qxLayerID && jdLayerID) {
                    if (treeNode.checked) {
                        map.getLayer(qxLayerID).show();
                        map.getLayer(jdLayerID).show();
                    } else {
                        map.getLayer(qxLayerID).hide();
                        map.getLayer(jdLayerID).hide();
                        qxGraphicsLayer.clear()
                    }
                }
            }
        }

        //点击子节点，显示属性表
        function localzTreeOnClick(event, treeId, treeNode) {
            var fid = treeNode.layerId;

            localFileName = treeNode.name + "的批量地址检索结果";

            var tableLayer = null;
            for (var i = 0; i < localDataFeatureLayers.length; i++) {
                if (localDataFeatureLayers[i].id === fid) {
                    tableLayer = localDataFeatureLayers[i];
                }
            }

            createFeatureTable(tableLayer);

            $("#map").css("height", "63%");
            $("#result").show();
        }


        fileParse = (responseText, layerListType) => {
            if (responseText.indexOf("java.lang") > -1) {
                failAlert("您加载的文件无法解析，请检查后重新上传！");
                return;
            }

            var index = responseText.lastIndexOf(".");
            var ext = responseText.substr(index + 1);
            var fileName = responseText.substr(0, index);

            if (responseText.substr(responseText.length - 1, 1) == "}") {
                //excel的内容
                if (responseText == '{}') {
                    failAlert("您加载的excel无内容，请检查后重新上传！");
                } else {
                    addDataType = "excel";
                    resultJSON = JSON.parse(responseText);
                    //字符串转json

                    var fileNameWithExt = resultJSON.fileName + ".xls";
                    localFileName = fileNameWithExt;

                    excel2Layer(resultJSON, fileNameWithExt, layerListType);
                    $("#mainio3").click();
                }
            } else if (ext == "csv") {
                addDataType = "csv";
                var fileNameWithExt = responseText;

                localFileName = fileNameWithExt;

                csv2Layer("files/" + responseText, fileNameWithExt, layerListType);
                $("#mainio3").click();
            } else if (ext == "shp") {
                addDataType = "shp";
                var fileNameWithExt = responseText.substr(responseText.lastIndexOf("/") + 1);

                localFileName = fileNameWithExt;

                shp2Layer("files/shp/" + responseText, fileNameWithExt, layerListType);
                $("#mainio3").click();
            } else if (ext == "json") {
                addDataType = "json";
                var fileNameWithExt = responseText;

                localFileName = fileNameWithExt;

                json2Layer("files/" + responseText, fileNameWithExt, layerListType);
                $("#mainio3").click();
            }
        }


        function addLocalNode(layerId, fileNameWithExt, layerListType) {
            var localLayerzTree = $.fn.zTree.getZTreeObj(layerListType);

            var rootNode = localLayerzTree.getNodesByFilter(function (node) {
                return node.level == 0;
            }, true);

            var newNode = {
                name: fileNameWithExt,
                layerId: layerId,
            };

            newNode = localLayerzTree.addNodes(rootNode, newNode);

            var node = localLayerzTree.getNodeByParam("layerId", layerId);
            localLayerzTree.checkNode(node, true, true);

            //地址匹配或复合检索时，直接打开属性表
            var lastFileName = fileNameWithExt.substr(fileNameWithExt.length - 6, 6);

            if (layerListType == "multiAddressLayerList" || (layerListType == "multiAroundLayerList" && lastFileName == "复合检索结果")) {
                var tId = node.tId;
                $("#" + tId + "_span").click();
            }
        }


        function excel2Layer(resultJSON, fileNameWithExt, layerListType) {
            // excelGeometries = [];
            excelGraphics = [];

            var fields = resultJSON.title;
            var cellValue = resultJSON.cellValue;
            var result = [];

            //去除字段前后的空格，防止影响xy字段的判断
            fields = fields.map(item => {
                return item.trim()
            })

            if (typeof (cellValue) == "undefined" || typeof (fields) == "undefined") {
                failAlert("您加载的excel无内容，请检查后重新上传！");
                return;
            }

            if (layerListType == "coordTransferLayerList" && (fields.indexOf("经度") == -1 || fields.indexOf("纬度") == -1)) {
                failAlert("您加载的excel文件中无经纬度坐标字段，请检查后重新上传！");
                return;
            } else if (layerListType != "coordTransferLayerList" && ((fields.indexOf("x") == -1 && fields.indexOf("X") == -1) || (fields.indexOf("y") == -1 && fields.indexOf("Y") == -1))) {
                failAlert("您加载的excel文件中无xy坐标字段，请检查后重新上传！");
                return;
            }

            for (var i = 0, il = cellValue.length; i < il; i++) {
                var templateContent = "<table style='word-break: break-all;'>";

                var item = cellValue[i];
                result[i] = {};
                for (var j = 0; j < fields.length; j++) {
                    var field = fields[j].trim();
                    if (field == "x" || field == "y" || field == "X" || field == "Y" || field == "经度" || field == "纬度") {
                        result[i][field] = Number(item[field]);
                    } else {
                        result[i][field] = item[field];
                    }

                    if (j % 2 == 1) {
                        str = "<tr><td class='leftTd'>" + field + "</td><td class='rightTd'>${" + field + "}</td></tr>";
                    } else {
                        str = "<tr bgcolor=\"#eeeeee\"><td class='leftTd'>" + field + "</td><td class='rightTd'>${" + field + "}</td></tr>";
                    }
                    templateContent = templateContent + str;
                }
                templateContent = templateContent + "</table>";

                //csv 转为 json,存入了result变量
                //循环每个坐标对，并将其写入图层中
                if (layerListType == "coordTransferLayerList") {
                    var x = result[i]["经度"];
                    var y = result[i]["纬度"];
                } else {
                    var x = result[i].x || result[i].X;
                    var y = result[i].y || result[i].Y;
                }

                if (typeof (x) != "undefined" && typeof (y) != "undefined") {
                    var point = new esri.geometry.Point(x, y, shanghaiSpatialRef);
                    var template = new InfoTemplate("${name}", templateContent);

                    var excelGraphic = new esri.Graphic(point, pointSymbol, result[i], template)

                    excelGraphics.push(excelGraphic);
                    // excelGeometries.push(point);

                    //缩放到第一个点
                    let zoomFlag = true;
                    if (zoomFlag) {
                        map.centerAndZoom(point, 1);
                        zoomFlag = false;
                    }
                }
            }

            setBufferParams(excelGraphics);

            createFeatureLayer(excelGraphics, fileNameWithExt, layerListType)
                .then(() => {
                    if (routeExtentFlag) {
                        $("#routeExtentFileUpload0_iframeContent").off("load");
                        $("#routeExtentFileUpload0_iframeContent").on("load", function () {
                            var responseText = $("#routeExtentFileUpload0_iframeContent")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML;
                            fileParse(responseText, "routeExceptionLayerList");
                        });
                    } else if (routeTimeFlag) {
                        $("#routeExtentFileUpload1_iframeContent").off("load");
                        $("#routeExtentFileUpload1_iframeContent").on("load", function () {
                            var responseText = $("#routeExtentFileUpload1_iframeContent")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML;
                            fileParse(responseText, "routeExceptionLayerList");
                        });
                    }

                    if (areaFeatureType == "cluster") {
                        createClusterLayer(excelGraphics, fileNameWithExt, layerListType);
                    }
                })

        }

        function csv2Layer(filePath, fileNameWithExt, layerListType) {
            csvGraphics = [];
            // csvGeometries = [];

            $.ajax({
                url: filePath,
                datatype: "json",
                async: false,
                contentType: 'text/json,charset=utf-8',
                data: {},
                success: function (data) {
                    var dataStr = new String(data);
                    var lines = dataStr.split('\n');
                    var result = [];
                    var fieldsStr = lines[0];
                    var fields = fieldsStr.split(',');
                    var valuesArr = lines.slice(1, lines.length);

                    fields = fields.map(item => {
                        return item.trim()
                    })

                    if (layerListType == "coordTransferLayerList" && (fields.indexOf("经度") == -1 || fields.indexOf("纬度") == -1)) {
                        failAlert("您加载的csv文件中无经纬度坐标字段，请检查后重新上传！");
                        return;
                    } else if (layerListType != "coordTransferLayerList" && ((fields.indexOf("x") == -1 && fields.indexOf("X") == -1) || (fields.indexOf("y") == -1 && fields.indexOf("Y") == -1))) {
                        failAlert("您加载的csv文件中无xy坐标字段，请检查后重新上传！");
                        return;
                    }

                    for (var i = 0, il = valuesArr.length; i < il; i++) {
                        if (valuesArr[i] != "") {
                            var templateContent = "<table style='word-break: break-all;'>";

                            var item = valuesArr[i].split(',');
                            result[i] = {};
                            for (var j = 0; j < fields.length; j++) {
                                var field = fields[j].trim();
                                if (field == "x" || field == "y" || field == "X" || field == "Y" || field == "经度" || field == "纬度") {
                                    result[i][field] = Number(item[j]);
                                } else {
                                    result[i][field] = item[j];
                                }

                                if (j % 2 == 1) {
                                    str = "<tr><td class='leftTd'>" + field + "</td><td class='rightTd'>${" + field + "}</td></tr>";
                                } else {
                                    str = "<tr bgcolor=\"#eeeeee\"><td class='leftTd'>" + field + "</td><td class='rightTd'>${" + field + "}</td></tr>";
                                }
                                templateContent = templateContent + str;
                            }
                            templateContent = templateContent + "</table>";

                            if (layerListType == "coordTransferLayerList") {
                                var x = result[i]["经度"];
                                var y = result[i]["纬度"];
                            } else {
                                var x = result[i].x || result[i].X;
                                var y = result[i].y || result[i].Y;
                            }

                            if (typeof (x) != "undefined" && typeof (y) != "undefined") {
                                var point = new esri.geometry.Point(x, y, shanghaiSpatialRef);
                                var template = new InfoTemplate("${name}", templateContent);

                                var csvGraphic = new esri.Graphic(point, pointSymbol, result[i], template)
                                // csvGeometries.push(point);
                                csvGraphics.push(csvGraphic);

                                let zoomFlag = true;
                                if (zoomFlag) {
                                    map.centerAndZoom(point, 1);
                                    zoomFlag = false;
                                }
                            }
                        }
                    }

                    setBufferParams(csvGraphics);
                    createFeatureLayer(csvGraphics, fileNameWithExt, layerListType)
                        .then(resolve => {
                            if (routeExtentFlag) {
                                $("#routeExtentFileUpload0_iframeContent").off("load");
                                $("#routeExtentFileUpload0_iframeContent").on("load", function () {
                                    var responseText = $("#routeExtentFileUpload0_iframeContent")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML;
                                    fileParse(responseText, "routeExceptionLayerList");
                                });
                            } else if (routeTimeFlag) {
                                $("#routeExtentFileUpload1_iframeContent").off("load");
                                $("#routeExtentFileUpload1_iframeContent").on("load", function () {
                                    var responseText = $("#routeExtentFileUpload1_iframeContent")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML;
                                    fileParse(responseText, "routeExceptionLayerList");
                                });
                            }

                            if (areaFeatureType == "cluster") {
                                createClusterLayer(csvGraphics, fileNameWithExt, layerListType);
                            }
                        })
                }
            });
        }


        function json2Layer(filePath, fileNameWithExt, layerListType) {
            // jsonGeometries = [];
            jsonGraphics = [];

            $.ajax({
                url: filePath,
                datatype: "json",
                async: false,
                contentType: 'text/json,charset=utf-8',
                data: {},
                success: function (data) {
                    var featureCollection = {
                        "layerDefinition": null,
                        "featureSet": data
                    };

                    var features = data.features;

                    if (features[0].geometry.hasOwnProperty("paths")) {
                        featureCollection.layerDefinition = {
                            "geometryType": data.geometryType,
                            "spatialReference": shanghaiSpatialRef,
                            "drawingInfo": {
                                "renderer": {
                                    "type": "simple",
                                    "symbol": {
                                        "color": lineColor,
                                        "width": 1,
                                        "type": "esriSLS",
                                        "style": "esriSLSSolid"
                                    }
                                }
                            }
                        };
                    } else if (features[0].geometry.hasOwnProperty("x")) {
                        featureCollection.layerDefinition = {
                            "geometryType": data.geometryType,
                            "spatialReference": shanghaiSpatialRef,
                            "drawingInfo": {
                                "renderer": {
                                    "type": "simple",
                                    "symbol": {
                                        "color": pointColor,
                                        "size": 8,
                                        "angle": 0,
                                        "xoffset": 0,
                                        "yoffset": 0,
                                        "type": "esriSMS",
                                        "style": "esriSMSCircle",
                                        "outline": {
                                            "color": pointOutlineColor,
                                            "width": 1,
                                            "type": "esriSLS",
                                            "style": "esriSLSSolid"
                                        }
                                    }
                                }
                            }
                        };
                    } else if (features[0].geometry.hasOwnProperty("rings")) {
                        featureCollection.layerDefinition = {
                            "geometryType": data.geometryType,
                            "spatialReference": shanghaiSpatialRef,
                            // "objectIdField": "ObjectID",
                            "drawingInfo": {
                                "renderer": {
                                    "type": "simple",
                                    "symbol": {
                                        'type': 'esriSFS',
                                        'style': 'esriSFSSolid',
                                        'color': polygonColor,
                                        'outline': {
                                            'type': 'esriSLS',
                                            'style': 'esriSLSSolid',
                                            'color': polygonOutlineColor,
                                            'width': 1
                                        }
                                    }
                                }
                            }
                        };
                    }

                    featureCollection.layerDefinition.fields = data.fields;

                    var attributes = data.features[0].attributes;

                    var infoTemplate = createInfoTemplate(attributes);;

                    var layerId = "localDataFeatureLayer" + localDataFeatureLayers.length;
                    var localDataFeatureLayer = new FeatureLayer(featureCollection, {
                        id: layerId,
                        spatialReference: shanghaiSpatialRef,
                        infoTemplate: infoTemplate,
                        visible: true
                    });

                    localDataFeatureLayers.push(localDataFeatureLayer);

                    map.addLayer(localDataFeatureLayers[localDataFeatureLayers.length - 1]);

                    addLocalNode(layerId, fileNameWithExt, layerListType);
                }
            });
        }

        function routeOutOfExtent(graphics) {
            let zoomFlag = true;

            let routeExtentGraphics = [];

            shpGeometries = shpGraphics.map(item => {
                return item.geometry
            })

            graphics.map((graphic) => {
                let isContains = false;

                const point = graphic.geometry;

                for (let i = 0; i < shpGeometries.length; i++) {
                    const polygon = shpGeometries[i];
                    if (polygon.contains(point)) { //判断点是否在多边形内，返回值为Boolean
                        isContains = true;
                        break;
                    }
                }

                if (!isContains) {
                    var sms = new PictureMarkerSymbol("img/marker/orange.gif", 25, 25);

                    var graphic = new esri.Graphic(point, sms, graphic.attributes);
                    routeExtentGraphics.push(graphic);

                    if (zoomFlag) {
                        map.centerAndZoom(point, 1);
                        zoomFlag = false;
                    }
                }
            });

            return routeExtentGraphics;
        }

        function routeInExtent(graphics) {
            let zoomFlag = true;

            let routeInExtentGraphics = [];

            shpGeometries = shpGraphics.map(item => {
                return item.geometry
            })

            graphics.map((graphic) => {
                let isContains = false;

                const point = graphic.geometry;

                for (let i = 0; i < shpGeometries.length; i++) {
                    const polygon = shpGeometries[i];
                    if (polygon.contains(point)) { //判断点是否在多边形内，返回值为Boolean
                        isContains = true;
                        break;
                    }
                }

                if (isContains) {
                    var sms = new PictureMarkerSymbol("img/marker/orange.gif", 25, 25);

                    var graphic = new esri.Graphic(point, sms, graphic.attributes);

                    routeInExtentGraphics.push(graphic);

                    // if (zoomFlag) {
                    //     map.centerAndZoom(point, 1);
                    //     zoomFlag = false;
                    // }
                }
            });

            return routeInExtentGraphics;
        }

        let timeUsed = (time, nextTime) => {
            let timeBetween = nextTime - time;
            let minutes = Math.floor(timeBetween / 1000 / 60);
            return minutes;
        }

        function shp2Layer(filePath, fileNameWithExt, layerListType) {
            shpGeometries = [];
            shpGraphics = [];

            shapefile.open(filePath).then(source => source.read().then(function log(result) {
                if (result.done) {
                    setBufferParams(shpGraphics);
                    createFeatureLayer(shpGraphics, fileNameWithExt, layerListType)
                        .then(resolve => {
                            if (areaFeatureType == "cluster") {
                                createClusterLayer(shpGraphics, fileNameWithExt, layerListType);
                            }

                            if (routeExtentFlag) {
                                exceptionGraphicsLayer.clear();
                                let routeExtentGraphics = []; //存储超出范围异常的点

                                if (csvGraphics.length != 0) {
                                    routeExtentGraphics = routeOutOfExtent(csvGraphics);
                                } else if (excelGraphics.length != 0) {
                                    routeExtentGraphics = routeOutOfExtent(excelGraphics);
                                }

                                // var zTree = $.fn.zTree.getZTreeObj(layerListType);
                                // var nodes=zTree.getNodes();
                                // var routeName=nodes[0].children[nodes[0].children.length-2].name;
                                if (routeExtentGraphics.length > 0) {
                                    var routeExtentName = localFileName + "超出服务范围分析结果";

                                    //需要判断shp图层加载完成后，再加载异常轨迹点图层
                                    //否则异常轨迹点图层的图层名会和shp图层一样

                                    createFeatureLayer(routeExtentGraphics, routeExtentName, layerListType)
                                        .then(resolve => {
                                            var sms = new PictureMarkerSymbol("img/marker/orange.gif", 25, 25);
                                            var render = new SimpleRenderer(sms);

                                            localDataFeatureLayers[localDataFeatureLayers.length - 1].setRenderer(render);

                                        })

                                } else {
                                    okAlert("未发现异常");
                                }

                                routeExtentFlag = false;
                            } else if (routeTimeFlag) {
                                let attr = csvGraphics;
                                let timeLimit = $("#timeLimitInput").val() || 3;

                                let routeInExtentGraphics = [];
                                let routeTimeExceptionGraphics = []; //存储时间异常的点

                                if (csvGraphics.length != 0) {
                                    routeInExtentGraphics = routeInExtent(csvGraphics);
                                } else if (excelGraphics.length != 0) {
                                    routeInExtentGraphics = routeInExtent(excelGraphics);
                                }

                                exceptionGraphicsLayer.clear();

                                if (routeInExtentGraphics.length > 0) {
                                    let zoomFlag = true;

                                    routeInExtentGraphics.map((graphic, index) => {
                                        if (index < routeInExtentGraphics.length - 1) {
                                            let nextGraphic = routeInExtentGraphics[index + 1];

                                            let point = graphic.geometry;
                                            let nextPoint = nextGraphic.geometry;

                                            let time = graphic.attributes["time"];
                                            time = convertDateFromString(time);

                                            let nextTime = routeInExtentGraphics[index + 1].attributes["time"];
                                            nextTime = convertDateFromString(nextTime);

                                            let timeBetween = timeUsed(time, nextTime);

                                            if (timeBetween > timeLimit) {
                                                var sms = new PictureMarkerSymbol("img/marker/orange.gif", 25, 25);

                                                var graphic0 = new esri.Graphic(point, sms, graphic.attributes);
                                                var graphic1 = new esri.Graphic(nextPoint, sms, nextGraphic.attributes);


                                                let coord0 = [point.x, point.y];
                                                let coord1 = [nextPoint.x, nextPoint.y];

                                                var tempLineJson = {
                                                    "paths": [
                                                        [coord0, coord1]
                                                    ],
                                                    "spatialReference": shanghaiSpatialRef
                                                };

                                                var patrolLineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([238, 69, 0]), 4);
                                                var polyline = new Polyline(tempLineJson);
                                                var graphic2 = new Graphic(polyline, patrolLineSymbol);
                                                exceptionGraphicsLayer.add(graphic2);

                                                // exceptionGraphicsLayer.add(graphic);
                                                // exceptionGraphicsLayer.add(graphic1);

                                                routeTimeExceptionGraphics.push(graphic0);
                                                routeTimeExceptionGraphics.push(graphic1);

                                                if (zoomFlag) {
                                                    map.centerAndZoom(point, 1);
                                                    zoomFlag = false;
                                                }
                                            }
                                        }

                                    });

                                    if (routeTimeExceptionGraphics.length == 0) {
                                        okAlert("未发现异常");
                                        return
                                    } else {
                                        var routeExtentName = localFileName + "长时间停留分析结果";

                                        createFeatureLayer(routeTimeExceptionGraphics, routeExtentName, layerListType)
                                            .then(resolve => {

                                                var sms = new PictureMarkerSymbol("img/marker/orange.gif", 25, 25);
                                                var render = new SimpleRenderer(sms);

                                                localDataFeatureLayers[localDataFeatureLayers.length - 1].setRenderer(render);
                                            })
                                    }


                                } else {
                                    okAlert("未发现异常");
                                }

                                routeTimeFlag = false;
                            }
                            return;
                        })
                } else {
                    var jsonf = geoJsonConverter();
                    var feature = jsonf.toEsri(result.value);
                    feature.geometry.spatialReference = shanghaiSpatialRef;

                    var featureType = result.value.geometry.type;
                    if (featureType == "Polygon" || featureType == "MultiPolygon") {
                        var sym = {
                            'type': 'esriSFS',
                            'style': 'esriSFSSolid',
                            'color': [125, 125, 125, 0.35],
                            'outline': {
                                'type': 'esriSLS',
                                'style': 'esriSLSSolid',
                                'color': [2, 134, 255],
                                'width': 1
                            }
                        };
                    } else if (featureType == "LineString" || featureType == "MultiLineString") {
                        var sym = {
                            "color": [255, 155, 0],
                            "width": 2,
                            "type": "esriSLS",
                            "style": "esriSLSSolid"
                        };
                    } else if (featureType == "Point" || featureType == "MultiPoint") {
                        var sym = {
                            "color": [238, 69, 0, 64],
                            "size": 6,
                            "angle": 0,
                            "xoffset": 0,
                            "yoffset": 0,
                            "type": "esriSMS",
                            "style": "esriSMSCircle",
                            "outline": {
                                "color": [238, 69, 0, 160],
                                "width": 1,
                                "type": "esriSLS",
                                "style": "esriSLSSolid"
                            }
                        };
                    }

                    feature.symbol = sym;

                    var attributes = feature.attributes;

                    var infoTemplate = createInfoTemplate(attributes);

                    feature.infoTemplate = infoTemplate;

                    var shpGraphic = new esri.Graphic(feature);

                    shpGraphics.push(shpGraphic);

                    return source.read().then(log);
                }
            })).catch(error => console.error(error.stack));
        }

        createFeatureLayer = async function (features, fileNameWithExt, layerListType) {
            if (features.length == 0) {
                failAlert("您加载的数据无法显示，请检查后重新上传！");
                return;
            }

            if (layerListType == "coordTransferLayerList" && !fileNameWithExt.endWith("的坐标转换结果")) {
                return;
            }
            var dz = {
                //数据的基本属性
                "displayFieldName": "",
                // "fieldAliases": {
                //     "x": "x",
                //     "y": "y",
                //     // "NAME": "NAME",
                // },
                // "geometryType": "esriGeometryPoint",
                "spatialReference": shanghaiSpatialRef,
            };

            if (features[0].geometry.hasOwnProperty("paths")) {
                dz.geometryType = "esriGeometryPolyline";
            } else if (features[0].geometry.hasOwnProperty("x")) {
                dz.geometryType = "esriGeometryPoint";
            } else if (features[0].geometry.hasOwnProperty("rings")) {
                dz.geometryType = "esriGeometryPolygon";
            }

            var attributes = features[0].attributes;
            var fields = [];
            var dzFeatures = [];

            var hasFID = false;

            for (var key in attributes) {
                if (key == "FID") {
                    hasFID = true;
                    var field = {
                        "name": key,
                        // "type": "esriFieldTypeDouble",
                        "type": "esriFieldTypeOID",
                        "alias": key,
                    };
                } else {
                    var field = {
                        "name": key,
                        // "type": "esriFieldTypeDouble",
                        "type": "esriFieldTypeString",
                        "alias": key,
                    };
                }

                fields.push(field);
            }
            if (!hasFID) {
                var ofield = {
                    "name": "FID",
                    // "type": "esriFieldTypeDouble",
                    "type": "esriFieldTypeOID",
                    "alias": "FID",
                };

                fields.push(ofield);
            }


            var count = 1;

            features.map((item) => {

                if (!hasFID) {
                    item.attributes.FID = count;
                    count++;
                }

                var dzFeature = {
                    "attributes": item.attributes,
                    "geometry": item.geometry,
                };

                dzFeatures.push(dzFeature);

            });

            dz.fields = fields;
            dz.features = dzFeatures;

            var featureSet = new esri.tasks.FeatureSet(dz);

            var featureCollection = {
                "layerDefinition": null,
                "featureSet": featureSet
            };

            if (features[0].geometry.hasOwnProperty("paths")) {
                featureCollection.layerDefinition = {
                    "geometryType": dz.geometryType,
                    "spatialReference": shanghaiSpatialRef,
                    "drawingInfo": {
                        "renderer": {
                            "type": "simple",
                            "symbol": {
                                "color": lineColor,
                                "width": 2,
                                "type": "esriSLS",
                                "style": "esriSLSSolid"
                            }
                        }
                    }
                };
            } else if (features[0].geometry.hasOwnProperty("x")) {
                featureCollection.layerDefinition = {
                    "geometryType": dz.geometryType,
                    "spatialReference": shanghaiSpatialRef,
                    "drawingInfo": {
                        "renderer": {
                            "type": "simple",
                            "symbol": {
                                "color": pointColor,
                                "size": 8,
                                "angle": 0,
                                "xoffset": 0,
                                "yoffset": 0,
                                "type": "esriSMS",
                                "style": "esriSMSCircle",
                                "outline": {
                                    "color": pointOutlineColor,
                                    "width": 1,
                                    "type": "esriSLS",
                                    "style": "esriSLSSolid"
                                }
                            }
                        }
                    }
                };
            } else if (features[0].geometry.hasOwnProperty("rings")) {
                featureCollection.layerDefinition = {
                    "geometryType": dz.geometryType,
                    "spatialReference": shanghaiSpatialRef,
                    // "objectIdField": "ObjectID",
                    "drawingInfo": {
                        "renderer": {
                            "type": "simple",
                            "symbol": {
                                'type': 'esriSFS',
                                'style': 'esriSFSSolid',
                                'color': polygonColor,
                                'outline': {
                                    'type': 'esriSLS',
                                    'style': 'esriSLSSolid',
                                    'color': polygonOutlineColor,
                                    'width': 1
                                }
                            }
                        }
                    }
                };
            }


            featureCollection.layerDefinition.fields = fields;

            var infoTemplate = createInfoTemplate(attributes);

            var layerId = "localDataFeatureLayer" + localDataFeatureLayers.length;

            const layer = await initlocalDataFeatureLayer(featureCollection, layerId, infoTemplate, features, fileNameWithExt, layerListType)

            // console.log("layer加载完成")

            if (layerListType == "areaCoverageLayerList") {
                $("#areaCoveragePanel").show();
                $("#bufferInput").focus();
            }

            return layer
        }


        function initlocalDataFeatureLayer(featureCollection, layerId, infoTemplate, features, fileNameWithExt, layerListType) {
            const promise = new Promise(resolve => {
                //featureCollection中的featureSet被限制50000个
                var localDataFeatureLayer = new FeatureLayer(featureCollection, {
                    id: layerId,
                    spatialReference: shanghaiSpatialRef,
                    infoTemplate: infoTemplate,
                    visible: true
                });

                localDataFeatureLayer.on("load", function (e) {
                    //匹配结果构造的featureLayer最大存储50000个，大于50000的自行添加
                    // if (layerListType == "multiAddressLayerList" && features.length > 50000) {
                    if (features.length > 50000) {
                        for (let i = 50000; i < features.length; i++) {
                            let graphic = features[i];
                            graphic.symbol = null;
                            graphic.infoTemplate = null;

                            localDataFeatureLayer.graphics.push(features[i]);
                        }
                    }
                    localDataFeatureLayers.push(localDataFeatureLayer);

                    map.addLayer(localDataFeatureLayers[localDataFeatureLayers.length - 1]);

                    if (layerListType != "clusterDisplay") {
                        addLocalNode(layerId, fileNameWithExt, layerListType);
                    }

                    //给每个FeatureLayer添加鼠标移入事件
                    localDataFeatureLayer.on("mouse-over", function (evt) {
                        // 鼠标进入FeatureLayer的要素时，鼠标变手型提醒
                        map.setMapCursor("pointer");
                        // //获取当前鼠标悬浮的graphic
                        selectedGraphic = evt.graphic;
                        ctxMenuForGraphics.bindDomNode(evt.graphic.getDojoShape().getNode());
                    });
                    localDataFeatureLayer.on("mouse-out", function (evt) {
                        map.setMapCursor("default");
                        ctxMenuForGraphics.unBindDomNode(evt.graphic.getDojoShape().getNode())
                    });
                    // console.log("layer onload")

                    resolve(localDataFeatureLayer);
                });


            })

            return promise;
        }

        createClusterLayer = function (inputGraphics, fileNameWithExt, layerListType) {
            areaFeatureType = "";
            if (inputGraphics.length > 0) {
                if (inputGraphics[0].geometry.hasOwnProperty("rings")) {
                    warningAlert("当前加载的shp文件为面图层，无法生成聚合图，请加载点图层")
                    return
                } else if (inputGraphics[0].geometry.hasOwnProperty("paths")) {
                    warningAlert("当前加载的shp文件为线图层，无法生成聚合图，请加载点图层")
                    return
                }
            } else {
                warningAlert("当前加载的图层为空，无法生成聚合图，请检查后重新加载")
                return
            }
            var centerXY = {
                "杨浦区": {
                    x: 5479.46,
                    y: 7211.366592,
                    count: 0
                },
                "虹口区": {
                    x: 1297.989599,
                    y: 3697.668416,
                    count: 0
                },
                "黄浦区": {
                    x: 1733.153528,
                    y: -2438.79151,
                    count: 0
                },
                "静安区": {
                    x: -2011.541709,
                    y: 5509.499484,
                    count: 0
                },
                "普陀区": {
                    x: -7613.377087,
                    y: 2696.258603,
                    count: 0
                },
                "长宁区": {
                    x: -8628.652953,
                    y: -2912.752167,
                    count: 0
                },
                "徐汇区": {
                    x: -3068.104735,
                    y: -7829.360968,
                    count: 0
                },
                "闵行区": {
                    x: -5025.034794,
                    y: -16222.96514,
                    count: 0
                },
                "宝山区": {
                    x: -6442.884988,
                    y: 17196.875426,
                    count: 0
                },
                "嘉定区": {
                    x: -21657.486661,
                    y: 13792.844203,
                    count: 0
                },
                "青浦区": {
                    x: -36854.737949,
                    y: -12013.565259,
                    count: 0
                },
                "松江区": {
                    x: -24025.225741,
                    y: -24189.378653,
                    count: 0
                },
                "奉贤区": {
                    x: 8049.114452,
                    y: -35785.099607,
                    count: 0
                },
                "浦东新区": {
                    x: 23578.194925,
                    y: -15052.12521,
                    count: 0
                },
                "崇明区": {
                    x: 8637.706079,
                    y: 44871.041695,
                    count: 0
                },
                "金山区": {
                    x: -22351.414715,
                    y: -44708.375642,
                    count: 0
                }
            };
            const quxianLayer = new FeatureLayer(quxianLayerUrl, {
                mode: FeatureLayer.MODE_SNAPSHOT,
                outFields: ["*"]
            });
            var query = new Query();
            query.where = "1=1";
            query.outFields = ["*"];
            query.returnGeometry = true;
            quxianLayer.queryFeatures(query, function (featureSet) {
                const qxPolygonGraphics = featureSet.features;
                var clusterGraphics = [];
                inputGraphics.map((graphic) => {
                    const point = graphic.geometry;
                    for (let i = 0; i < qxPolygonGraphics.length; i++) {
                        const polygon = qxPolygonGraphics[i].geometry;
                        if (polygon.contains(point)) { //判断点是否在多边形内，返回值为Boolean
                            centerXY[qxPolygonGraphics[i].attributes[districtNameField]].count++;
                            break;
                        }
                    }
                });
                for (var key in centerXY) {
                    var x = centerXY[key].x;
                    var y = centerXY[key].y;
                    // var x = centerXY[key].x + (500 - Math.random() * 1000);
                    // var y = centerXY[key].y + (500 - Math.random() * 1000);
                    var qxpoint = new Point(x, y, shanghaiSpatialRef);
                    let attributes = {
                        "行政区": key,
                        "类型": "区县",
                        "数量": centerXY[key].count
                    };
                    var qxGraphic = new esri.Graphic(qxpoint, {}, attributes, {});
                    clusterGraphics.push(qxGraphic);
                }

                const jiedaoLayer = new FeatureLayer(jiedaoLayerUrl, {
                    mode: FeatureLayer.MODE_SNAPSHOT,
                    outFields: ["*"]
                });
                var query = new Query();
                query.where = "1=1";
                query.outFields = ["*"];
                query.returnGeometry = true;
                jiedaoLayer.queryFeatures(query, function (featureSet) {
                    const jdPolygonGraphics = featureSet.features;
                    let jdCenterXY = {};
                    jdPolygonGraphics.forEach(item => {
                        jdCenterXY[item.attributes[streetNameField]] = {
                            center: item.geometry.getCentroid(),
                            count: 0
                        };
                    });
                    inputGraphics.map((graphic) => {
                        const point = graphic.geometry;
                        for (let i = 0; i < jdPolygonGraphics.length; i++) {
                            const polygon = jdPolygonGraphics[i].geometry;
                            if (polygon.contains(point)) { //判断点是否在多边形内，返回值为Boolean
                                jdCenterXY[jdPolygonGraphics[i].attributes[streetNameField]].count++;
                                break;
                            }
                        }
                    });
                    for (var key in jdCenterXY) {
                        const jdpoint = jdCenterXY[key].center;
                        let attributes = {
                            "行政区": key,
                            "类型": "街道镇",
                            "数量": jdCenterXY[key].count
                        };
                        var jdGraphic = new esri.Graphic(jdpoint, {}, attributes, {});
                        clusterGraphics.push(jdGraphic);
                    }
                    areaFeatureType = "";
                    fileNameWithExt = fileNameWithExt + "的聚合图";
                    createFeatureLayer(clusterGraphics, fileNameWithExt, layerListType).then((layer) => {
                        layer.setVisibility(false);
                        const clusterLayer = layer;
                        clusterGraphicsObj[clusterLayer.id] = {
                            graphic: clusterGraphics
                        };
                        let qxGraphics = clusterGraphicsObj[layer.id].graphic.filter((graphic) => {
                            return graphic.attributes["类型"] == "区县";
                        });
                        let jdGraphics = clusterGraphicsObj[layer.id].graphic.filter((graphic) => {
                            return graphic.attributes["类型"] == "街道镇";
                        });
                        layerListType = "clusterDisplay";
                        //聚合图的样式
                        var lightgreen = new Color([76, 175, 80, 0.6]);
                        var lightgreen2 = new Color([76, 175, 80]);
                        var clusterSymbol = new SimpleMarkerSymbol("solid", 90, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, lightgreen2, 0.8), lightgreen);
                        var render = new SimpleRenderer(clusterSymbol);
                        var statesLabel = new TextSymbol().setColor(new Color("#fff"));
                        statesLabel.font.setSize("12pt");
                        statesLabel.font.setWeight(600);
                        var labelClass = new LabelClass({
                            "labelExpressionInfo": {
                                "value": "{行政区}\n{数量}"
                            },
                            "labelPlacement": "center-center",
                        });
                        labelClass.symbol = statesLabel;

                        createFeatureLayer(qxGraphics, fileNameWithExt, layerListType).then((layer) => {
                            clusterGraphicsObj[clusterLayer.id].qxLayerID = layer.id;
                            layer.setRenderer(render);
                            layer.setLabelingInfo([labelClass]);
                            layer.setMaxScale(50001);

                            layer.on("mouse-over", function (e) {
                                var query = new Query();
                                query.where = districtNameField + " = '" + e.graphic.attributes["行政区"] + "'";
                                query.outFields = ["*"];
                                query.returnGeometry = true;
                                quxianLayer.queryFeatures(query, function (featureSet) {
                                    featureSet.features.forEach(item => {
                                        qxGraphicsLayer.add(item)
                                    })
                                })
                            })

                            layer.on("mouse-out", function (e) {
                                qxGraphicsLayer.clear()
                            })

                            map.centerAndZoom(new Point(0, 0, shanghaiSpatialRef), 0);

                            createFeatureLayer(jdGraphics, fileNameWithExt, layerListType).then((layer) => {
                                clusterGraphicsObj[clusterLayer.id].jdLayerID = layer.id;
                                layer.setRenderer(render);
                                layer.setLabelingInfo([labelClass]);
                                layer.setMinScale(50000);

                                layer.on("mouse-over", function (e) {
                                    var query = new Query();
                                    query.where = streetNameField + " = '" + e.graphic.attributes["行政区"] + "'";
                                    query.outFields = ["*"];
                                    query.returnGeometry = true;
                                    jiedaoLayer.queryFeatures(query, function (featureSet) {
                                        featureSet.features.forEach(item => {
                                            qxGraphicsLayer.add(item)
                                        })
                                    })
                                })

                                layer.on("mouse-out", function (e) {
                                    qxGraphicsLayer.clear()
                                })
                            });
                        });
                    });
                }, function (jderr) {
                    failAlert("街道镇服务异常")
                });
            }, function (qxerr) {
                failAlert("区县服务异常")
            });
        }

        function createInfoTemplate(attributes) {
            var templateContent = "<table style='word-break: break-all;'>";
            var j = 0,
                str = "";
            for (var key in attributes) {
                if (j % 2 == 1) {
                    str = "<tr><td class='leftTd'>" + key + "</td><td class='rightTd'>${" + key + "}</td></tr>";
                } else {
                    str = "<tr bgcolor=\"#eeeeee\"><td class='leftTd'>" + key + "</td><td class='rightTd'>${" + key + "}</td></tr>";
                }
                templateContent = templateContent + str;
                j++;
            }
            templateContent = templateContent + "</table>";
            var infoTemplate = new InfoTemplate("${name}", templateContent);

            return infoTemplate;
        }

        let convertDateFromString = (dateString) => {
            if (dateString) {
                dateString = dateString.replace(/-/g, "/")
                dateString = dateString.replace(/\./g, "/")
                var date = new Date(dateString);
                return date;
            }
        }

    });